import java.net.*;
import java.io.*;

public class ListenHandler extends Thread
{
    Socket socket = null;
    Mazewar mazewar;
    public ListenHandler(Socket soc, Mazewar mazewar)
    {
        this.socket = soc;
        this.mazewar = mazewar;
    }

    public void run()
    {
        try
        {
            if (socket.isClosed())
                System.err.println("Socket.accept() is closed");
            ObjectInputStream fromPeer = new ObjectInputStream(socket.getInputStream());
            GamePacket packetFromPeer = (GamePacket)fromPeer.readObject();                        

            if (packetFromPeer.MsgType == GamePacket.MessageType.REQUEST_PEER_LIST)
            {
                GamePacket packetToPeer = new GamePacket();
                packetToPeer.MsgType = GamePacket.MessageType.PEER_LIST_ACK;
                packetToPeer.peers = mazewar.peers;
                packetToPeer.me = mazewar.myself;
                Socket peerSocket = new Socket(packetFromPeer.me.hostname, packetFromPeer.me.port);
                sendPacket(packetToPeer, peerSocket);
                peerSocket.close();
                System.err.println("Received Packet: REQUEST_PEER_LIST");
            }
			else if (packetFromPeer.MsgType == GamePacket.MessageType.UPDATE)
			{
				System.out.println("Received the update message.");
				if (packetFromPeer.MsgAction == GamePacket.Action.UP)
				{
					System.out.println("Got UP");
					Client cMove = (Client)mazewar.clientList.get(packetFromPeer.me);
					//mazewar.maze.moveClientForward(cMove);
					cMove.forward();
				}
				else if (packetFromPeer.MsgAction == GamePacket.Action.DOWN)
				{
					System.out.println("Got DOWN");
					Client cMove = (Client)mazewar.clientList.get(packetFromPeer.me);
					//mazewar.maze.moveClientBackward(cMove);
					cMove.backup();
				}
				else if (packetFromPeer.MsgAction == GamePacket.Action.LEFT)
				{
					System.out.println("Got LEFT");
					Client cMove = (Client)mazewar.clientList.get(packetFromPeer.me);
					//mazewar.maze.rotateClientLeft(cMove);
					cMove.turnLeft();
				}
				else if (packetFromPeer.MsgAction == GamePacket.Action.RIGHT)
				{
					System.out.println("Got RIGHT");
					Client cMove = (Client)mazewar.clientList.get(packetFromPeer.me);
					//mazewar.maze.rotateClientRight(cMove);
					cMove.turnRight();
				}
				else if (packetFromPeer.MsgAction == GamePacket.Action.FIRE)
				{
					System.out.println("Got Fire");
					Client cMove = (Client)mazewar.clientList.get(packetFromPeer.me);
					cMove.fire();
				}
			}
			else if (packetFromPeer.MsgType == GamePacket.MessageType.PEER_LIST_ACK)
			{
				//mazewar.peers = packetFromPeer.peers;
				System.err.println("Received Packet: PEER_LIST_ACK");
				System.err.println("Number of Peers: " + packetFromPeer.peers.size());
				for (int i = 0; i < packetFromPeer.peers.size(); i++)
				{

					Peer p = (Peer)packetFromPeer.peers.get(i);
					GamePacket packetToPeer = new GamePacket();
					packetToPeer.MsgType = GamePacket.MessageType.REGISTER;
					packetToPeer.me = mazewar.myself;

					Point myloc = mazewar.getLoc();
					Direction mydir = mazewar.getDir();
					packetToPeer.locationX = myloc.getX();
					packetToPeer.locationY = myloc.getY();
					packetToPeer.direction = mydir.getDirection();
				
					Socket peerSocket = new Socket(p.hostname, p.port);
					sendPacket(packetToPeer, peerSocket);
					peerSocket.close();
					System.err.println("Sending REGISTER");
				}
			}
			else if (packetFromPeer.MsgType == GamePacket.MessageType.REGISTER)
			{
				System.err.println("Received Packet: REGISTER <" + packetFromPeer.me.name + ", " + packetFromPeer.locationX + ", " + packetFromPeer.locationY + ", " + packetFromPeer.direction + ">");

                mazewar.add_remote_client(packetFromPeer);

				GamePacket packetToPeer = new GamePacket();
				packetToPeer.MsgType = GamePacket.MessageType.REGISTER_ACK;
				packetToPeer.peers = mazewar.peers;
				packetToPeer.me = mazewar.myself;

				
				//--Send the peer direction--
				Point myloc = mazewar.getLoc();
				Direction mydir = mazewar.getDir();
				packetToPeer.locationX = myloc.getX();
				packetToPeer.locationY = myloc.getY();
				packetToPeer.direction = mydir.getDirection();
	
				Socket peerSocket = new Socket(packetFromPeer.me.hostname, packetFromPeer.me.port);
				sendPacket(packetToPeer, peerSocket);
				peerSocket.close();
			}
			else if (packetFromPeer.MsgType == GamePacket.MessageType.REGISTER_ACK)
			{
				System.err.println("Received Packet: REGISTER_ACK");
				System.out.println("Client direction:" + packetFromPeer.direction);
				mazewar.add_remote_client(packetFromPeer);
			}
			else if (packetFromPeer.MsgType == GamePacket.MessageType.BYE)
			{
				System.err.println("Received Packet: BYE");
				mazewar.remove_remote_client(packetFromPeer.me);
			}
			else if (packetFromPeer.MsgType == GamePacket.MessageType.KILLED)
			{
				System.out.println(packetFromPeer.targetName + " got killed!!");
				mazewar.vaporize_remote_client(packetFromPeer);
			}
			

            fromPeer.close();
            socket.close();
        }
        catch(Exception ex) {
            ex.printStackTrace();
        }
    }

    void sendPacket(GamePacket packet, Socket peerSocket) throws Exception
    {
        ObjectOutputStream toPeer = new ObjectOutputStream(peerSocket.getOutputStream());
        toPeer.writeObject(packet);
        toPeer.close();
    }
}
